// Copyright (c) 2016, XMOS Ltd, All rights reserved
// xflash  --boot-partition-size 0x100000 --factory *.bin  --upgrade 1 *.bin
// "--boot-partition-size 0x100000 " Set up partitions
#if 1
#include <xs1.h>
#include <platform.h>
#include <quadflashlib.h>
#include <timer.h>
#include <print.h>
#include "xua_conf.h"
#include "updata.h"
#include <stdio.h>

//#define LOG_BUG  printf
extern fl_QSPIPorts p_qflash;

#define MCU_VER                 0x0001     // MCU版本
#define HARDWARE_VER            1          // 硬件版本
#define SOF_VER                 (MCU_VER <<16 | BCD_DEVICE_J<<12|BCD_DEVICE_M<<8|BCD_DEVICE_N<<4|HARDWARE_VER)// 版本信息更新
#define SIMPLEFLY_FLAG          0x5450445a // 产品标识

// 前256字节存储头数据，256字节后存正文数据
void write_to_flash(void)
{
    int result = 0;
    unsigned char my_page1[256];
    unsigned char my_page[256];
    unsigned char page_buf[256];
    unsigned int num=0;
    unsigned int num2=0;
    unsigned int ver=0;
    unsigned int chacksum=0;
    for (int i = 0; i < 256; i++ ){
      my_page[i] = 0x00;
      page_buf[i] = 0x00;
      my_page1[i] = 0x00;
    }
    num  = sizeof(updata);
    num2 = sizeof(updata)%256;

    // 初始化
    //result = fl_connectToDevice(p_qflash, myFlashDevices, sizeof(myFlashDevices) / sizeof(fl_QuadDeviceSpec)); 
    result = fl_connect(p_qflash);
    if (result)
    {
#ifdef LOG_BUG
        LOG_BUG("error:%d\n", result);
#endif
        return ;
    }
#ifdef LOG_BUG
    LOG_BUG( "FLASH size: %d bytes.\n",fl_getFlashSize());  // 闪存容量
    LOG_BUG( "FLASH page size: %d bytes.\n",fl_getPageSize());// 闪存页面大小
    LOG_BUG( "FLASH data partition size: %d bytes. \n", fl_getDataPartitionSize()); // 闪存数据分区大小
    LOG_BUG( "FLASH number of pages in data partition: %d \n",fl_getNumDataPages() ); //数据分区中的闪存页面数量
    LOG_BUG( "FLASH number of sectors in data partition: %d\n",fl_getNumDataSectors() ); // 返回分区中的扇区数
    LOG_BUG( "FLASH data sector size: %d bytes.\n" ,fl_getDataSectorSize(0)); // 闪存数据扇区大小
    //unsigned fl_eraseDataSector 分区中第 n 个扇区的大小
#endif

    if(num/256+1 > fl_getNumDataPages())
    {
#ifdef LOG_BUG
        LOG_BUG("data-overrun error\n");
#endif
        return ;
    }

    fl_readDataPage(0, my_page);

    ver = (my_page[3]<<24)|(my_page[2]<<16)|(my_page[1]<<8)|(my_page[0]);
    if((SOF_VER != ver)||(ver == 0XFFFFFFFF))// 如果为空或者未写入则写入flash中
    {
        //if((SOF_VER&0xffff0000) != (ver&0xffff0000))//MCU版本变更则更新 
        {
            #ifdef LOG_BUG
            LOG_BUG( "fl_eraseAllDataSectors\n");
            #endif
            if(0 != fl_eraseAllDataSectors()) // 擦除分区中所有扇区 fl_eraseDataSector(0); 擦除一个扇区
            {
                #ifdef LOG_BUG
                LOG_BUG( "Could not erase the data partition\n");
                #endif
                return;
            }

            // 写入固件数据
            for(int i = 0; i <(num/256+1); i++ )
            {
                if(i<num/256)
                {
                    for(int j=0;j < 256; j++ )
                    {
                        chacksum += updata[i*256+j];
                        page_buf[j] = ~updata[i*256+j]; // 做一下翻转
                    }
                }
                else
                {
                    for(int j=0; j < 256; j++ )
                    {
                        if(j<num2)
                        {
                            chacksum += updata[i*256+j];
                            page_buf[j] = ~updata[i*256+j];
                        }
                        else
                        {
                            page_buf[j] = 0xff;
                        }
                    }
                }

                if(fl_writeDataPage(i+1,page_buf))
                {
                    fl_writeDataPage(i+1,page_buf);
                }
            }
        }

        for (int i = 0; i < 256; i++ ){
              my_page[i] = 0x00;
              page_buf[i] = 0xFF;
        }
        // 版本
        page_buf[0] =  SOF_VER&0xff;
        page_buf[1] = (SOF_VER>>8)&0xff;
        page_buf[2] = (SOF_VER>>16)&0xff;
        page_buf[3] = (SOF_VER>>24)&0xff;
        page_buf[4] =  SIMPLEFLY_FLAG&0xff;
        page_buf[5] = (SIMPLEFLY_FLAG>>8)&0xff;
        page_buf[6] = (SIMPLEFLY_FLAG>>16)&0xff;
        page_buf[7] = (SIMPLEFLY_FLAG>>24)&0xff;
        page_buf[8] =  chacksum&0xff;
        page_buf[9] =  (chacksum>>8)&0xff;
        page_buf[10] = (chacksum>>16)&0xff;
        page_buf[11] = (chacksum>>24)&0xff;
        page_buf[12] =  num&0xff;
        page_buf[13] = (num>>8)&0xff;
        page_buf[14] = (num>>16)&0xff;
        page_buf[15] = (num>>24)&0xff;

#ifdef LOG_BUG
        LOG_BUG("num:%d \n", num);
        LOG_BUG("chacksum:%d \n", chacksum);
        LOG_BUG("SIMPLEFLY_FLAG:0x%x \n", SIMPLEFLY_FLAG);
        LOG_BUG("ver-VER-ver: 0x%x != 0x%x", ver, SOF_VER);
#endif
 
        if(fl_writeDataPage(0, page_buf))
        {
            fl_writeDataPage(0, page_buf);
        }

        fl_readDataPage(0, my_page);
        ver = (my_page[3]<<24)|(my_page[2]<<16)|(my_page[1]<<8)|(my_page[0]);
        
#ifdef LOG_BUG
        LOG_BUG(" == 0x%x\n", ver);
#endif

        if(SOF_VER == ver)
        {
            //set_gpio(p_mcu_updata, 1); // 该IO接到MCU复位脚上用于重启声卡设备
#ifdef LOG_BUG
            LOG_BUG("Updata ok!\n");
        }
        else
        {
            LOG_BUG("Updata Error!\n");
#endif
        }
      
    }
#ifdef LOG_BUG    
    else 
    {
        LOG_BUG("NO updata \n");
    }
#endif
    fl_disconnect();
}
#endif

//#define USER_MAIN_CORES on tile[0]: {\
//                                       write_to_flash();\
//                                   }